﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;
using OpenExpressApp.MetaAttribute;
using System.Reflection;
using System.Collections;
using OpenExpressApp.Command;
using OpenExpressApp.Types;
using System.Diagnostics;
using OpenExpressApp.MetaModel;
using System.Windows.Media;
using Csla;

namespace OpenExpressApp
{
    /// <summary>
    /// 应用程序模型
    /// </summary>
    public static class ApplicationModel
    {
        /// <summary>
        /// 所有的实体信息
        /// </summary>
        private static List<BusinessObjectInfo> _allEntityInfos = new List<BusinessObjectInfo>();

        /// <summary>
        /// Key：命令名。
        /// Value：不可以使用这个命令的业务对象模型集合
        /// </summary>
        private static Dictionary<string, IList<BusinessObjectInfo>> _notVisibleCommands = new Dictionary<string, IList<BusinessObjectInfo>>();

        private static CommandCollection _commands = new CommandCollection();

        /// <summary>
        /// 应用程序中所有的命令对象
        /// </summary>
        public static CommandCollection Commands
        {
            get
            {
                return _commands;
            }
        }

        /// <summary>
        /// 存储InPermissionAttribute元信息
        /// </summary>
        public static Dictionary<Type, Type> TypeOwnerInPermission = new Dictionary<Type, Type>();

        /// <summary>
        /// 为这个业务对象模型设定某个命令不可见
        /// </summary>
        /// <param name="cmd"></param>
        /// <param name="bOInfo"></param>
        public static void AddNotVisibleCommand(string cmd, BusinessObjectInfo bOInfo)
        {
            IList<BusinessObjectInfo> list = null;
            if (_notVisibleCommands.TryGetValue(cmd, out list) == false)
            {
                list = new List<BusinessObjectInfo>();
                _notVisibleCommands[cmd] = list;
            }

            if (list.Contains(bOInfo) == false)
            {
                list.Add(bOInfo);
            }
        }

        /// <summary>
        /// 为这个业务对象模型设定某个命令可见
        /// </summary>
        /// <param name="cmd"></param>
        /// <param name="bOInfo"></param>
        public static void RemoveNotVisibleCommand(string cmd, BusinessObjectInfo bOInfo)
        {
            IList<BusinessObjectInfo> list = null;
            if (_notVisibleCommands.TryGetValue(cmd, out list))
            {
                list.Remove(bOInfo);
            }
        }

        /// <summary>
        /// 判断一个特定的命令是否对于这个业务对象模型是不可见的
        /// </summary>
        /// <param name="cmd"></param>
        /// <param name="bOInfo"></param>
        /// <returns></returns>
        public static bool IsNotVisibleCommand(string cmd, BusinessObjectInfo bOInfo)
        {
            IList<BusinessObjectInfo> list = null;
            return _notVisibleCommands.TryGetValue(cmd, out list) && list.Contains(bOInfo);
        }

        /// <summary>
        /// 获取所有的实体信息
        /// </summary>
        /// <returns></returns>
        public static IList<BusinessObjectInfo> GetAllEntityInfos()
        {
            return _allEntityInfos.AsReadOnly();
        }

        public static IEnumerable<BusinessObjectInfo> GetAllModules()
        {
            return _allEntityInfos.Where(e => e.IsDefaultObject && e.DefaultObjectAttribute.ShowInModule);
        }

        /// <summary>
        /// 查找指定类型对应的业务对象模型元数据
        /// 
        /// 如果没有查找到，则生成并存储一个新的。
        /// </summary>
        /// <param name="boType"></param>
        /// <returns></returns>
        public static BusinessObjectInfo AddBusinessObject(Type boType)
        {
            BusinessObjectInfo info = _allEntityInfos.FirstOrDefault(e => e.BOType == boType);
            if (info == null)
            {
                info = new BusinessObjectInfo(boType);

                _allEntityInfos.Add(info);
            }
            return info;
        }

        /// <summary>
        /// 同AddBusinessObject方法
        /// </summary>
        /// <param name="boType"></param>
        /// <returns></returns>
        public static BusinessObjectInfo GetBusinessObjectInfo(Type boType)
        {
            return AddBusinessObject(boType);
        }

        public static BusinessObjectInfo GetBusinessObjectInfo(Guid businessObjectId)
        {
            BusinessObjectInfo info = _allEntityInfos.FirstOrDefault(e => e.Id == businessObjectId);
            Debug.Assert(null != info, String.Format("不存在{0}的业务对象类", businessObjectId.ToString()));
            return info;
        }

        #region 简单实现View和Entity的映射
        //目前这些信息，全部都是存储在BusinessObjectInfo类中。

        public static IEntityViewInfo ViewInfo(this IEntityInfo entity)
        {
            return entity as IEntityViewInfo;
        }

        public static IEntityPropertyViewInfo ViewInfo(this IEntityPropertyInfo meta)
        {
            return meta as IEntityPropertyViewInfo;
        }

        public static IPropertyViewInfo ViewInfo(this IPropertyInfo meta)
        {
            return meta as IPropertyViewInfo;
        }

        public static ICommandViewInfo ViewInfo(this ICommand meta)
        {
            return meta as ICommandViewInfo;
        }

        #endregion
    }
}